#include "pyvim.h"

PyObject *WINDOW_SET = NULL;	/* a set stored references of all windows */

PyDoc_STRVAR(frame_doc,
"Object for window layout");

static PyObject *
frame_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
	return type->tp_alloc(type, 0);
}

static int
frame_init(PvFrame *self, PyObject *args, PyObject *kwds)
{
	if (!PyArg_ParseTuple(args, "ii|i", &self->height, &self->width, 
				&self->layout))
		return -1;
	return 0;
}

static void
frame_dealloc(PyObject *self)
{
	PyObject *p, *q;
	if (FR_CHILD(self) == NULL) 
		Py_XDECREF(FR_WIN(self));
	else {
		p = q = FR_CHILD(self);
		while (q != NULL) {
			p = q;
			q = FR_NEXT(p);
			Py_DECREF(p);
		}
	}
}

PyObject *
PvFrame_Split(PyObject *self, int dir)
{
	PyObject *f1 = NULL;
	PyObject *f2 = NULL;

	if (FR_LAYOUT(self) != FR_LEAF) {
		PyErr_SetString(PyExc_RuntimeError,
				"Can't split a frame not a leaf node!");
		return NULL;
	}

	f1 = self;
	self = PyObject_CallFunction((PyObject *)&PvFrame_Type, "ii", 
			FR_HEIGHT(f1), FR_WIDTH(f1));
	if (dir == FSP_HOR) {
	}else if (dir == FSP_VER) {
	}
}

static PyObject *
frame_spilt(PyObject *self, PyObject *args)
{
	int dir;

	if (!PyArg_ParseTuple(args, "i", &dir))
		return NULL;
	Py_RETURN_NONE;
}

static PyObject *
frame_insert(PyObject *self, PyObject *args)
{

}

static PyGetSetDef frame_getseters[] = {
	//{"length", (getter)buffer_getlength, (setter)buffer_setlength, 
	//	"The total number of buffer lines"},
	{NULL}
};

static PyMemberDef frame_members[] = {
	{"win", T_OBJECT, offsetof(PvFrame, win), 0, 
		"if frame is leaf node, it contain this win"},
	{"child", T_OBJECT, offsetof(PvFrame, child), 0, 
		"the first child list"},
	{"parent", T_OBJECT, offsetof(PvFrame, parent), 0, 
		"parent frame of this frame"},
	{"prev", T_OBJECT, offsetof(PvFrame, prev), 0, 
		"prev frame of this frame"},
	{"next", T_OBJECT, offsetof(PvFrame, next), 0, 
		"next frame of this frame"},
	{"height", T_INT, offsetof(PvFrame, height), 0, 
		"height of this frame"},
	{"width", T_INT, offsetof(PvFrame, width), 0, 
		"width of this frame"},
	{"layout", T_INT, offsetof(PvFrame, layout), 0, 
		"the layout of this frame items"},
	{"top", T_INT, offsetof(PvFrame, top), 0, 
		"first row in the screen"},
	{"left", T_INT, offsetof(PvFrame, left), 0, 
		"leftmost col in the screen"},
	{NULL}
};

static PyMethodDef frame_methods[] = {
	//{"read", (PyCFunction)buffer_read, METH_VARARGS,
	//	buffer_read_doc},
	{NULL, NULL}
};


PyTypeObject PvFrame_Type = {
	PyObject_HEAD_INIT(0)
        "pyvim.frame",		/* tp_name */
        sizeof(PvFrame),		/* tp_basicsize */
        0,				/* tp_itemsize */
        frame_dealloc,		/* tp_dealloc */
        0,				/* tp_print */
        0,				/* tp_getattr */
        0,				/* tp_setattr */
        0,				/* tp_reserved */
        0,				/* tp_repr */
        0,				/* tp_as_number */
        0,				/* tp_as_sequence */
        0,				/* tp_as_mapping */
        0,				/* tp_hash */
        0,				/* tp_call */
        0,				/* tp_str */
        PyObject_GenericGetAttr,	/* tp_getattro */
        0,				/* tp_setattro */
        0,				/* tp_as_buffer */
        Py_TPFLAGS_DEFAULT,		/* tp_flags */
        frame_doc,		/* tp_doc */
        0,				/* tp_traverse */
        0,				/* tp_clear */
        0,				/* tp_richcompare */
        0,				/* tp_weaklistoffset */
        0,				/* tp_iter */
        0,				/* tp_iternext */
        frame_methods,		/* tp_methods */
        frame_members,				/* tp_members */
        frame_getseters,				/* tp_getset */
        0,				/* tp_base */
        0,				/* tp_dict */
        0,				/* tp_descr_get */
        0,				/* tp_descr_set */
        0,				/* tp_dictoffset */
        (initproc)frame_init,				/* tp_init */
        0,				/* tp_alloc */
        frame_new,				/* tp_new */
        0,				/* tp_free */
        0,				/* tp_is_gc */
};

PyDoc_STRVAR(window_doc,
"window for display");

static PyObject *
window_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
	return type->tp_alloc(type, 0);
}

static int
window_init(PvWindow *self, PyObject *args, PyObject *kwds)
{
	if (!PyArg_ParseTuple(args, "O|O", &self->frame, &self->buffer))
		return -1;

	if (!PvFrame_CheckExact(self->frame)) {
		PyErr_SetString(PyExc_TypeError, "Error type of the frame args");
		return -1;
	}
	if (self->buffer == NULL) {
		self->buffer = PyObject_CallObject((PyObject *)&PvBuffer_Type, NULL);
	}

	if (!PvBuffer_CheckExact(self->buffer)) {
		PyErr_SetString(PyExc_TypeError, "Error type of the buffer args");
		return -1;
	}

	Py_INCREF(self->frame);
	Py_INCREF(self->buffer);

	self->status_height = 1;
	self->top = FR_TOP(self->frame);
	self->left = FR_LEFT(self->frame);
	self->width = FR_WIDTH(self->frame) - self->vsep_width;
	self->height = FR_HEIGHT(self->frame) - self->status_height;
	self->tabstop = DEFAULT_TAB_STOP;
	self->lines = PyMem_New(Py_UNICODE, self->width * self->height);
	Py_UNICODE_FILL(self->lines, ' ', self->width * self->height);

	if (WINDOW_SET == NULL) {
		WINDOW_SET = PySet_New(NULL);
		if (WINDOW_SET == NULL)
			return -1;
	}
	PySet_Add(WINDOW_SET, (PyObject *)self);
	return 0;
}

static void
window_dealloc(PyObject *self)
{
	Py_XDECREF(WIN_FRAME(self));
	Py_XDECREF(WIN_BUF(self));

	if (WIN_LINES(self) != NULL)
		PyMem_Free(WIN_LINES(self));
}

PyObject *
PvWindow_Remove(PyObject *win) 
{
	if (!PvWindow_CheckExact(win)) {
		PyErr_SetString(PyExc_TypeError, "args win type must be window");
		return NULL;
	}

	if (PySet_Discard(WINDOW_SET, win) == -1)
		return NULL;
	Py_RETURN_NONE;
}

PyDoc_STRVAR(window_remove_doc,
"window.remove(window)\n"
"remove the window from windows set\n");

static PyObject *
window_remove(PyObject *args)
{
	PyObject *win;
	if (!PyArg_ParseTuple(args, "O", &win)) 
		return NULL;
	return PvWindow_Remove(win);
}

PyDoc_STRVAR(window_getwindows_doc,
"window.getwindows()\n"
"return a set stored all windows");
static PyObject *
window_getwindows()
{
	if (WINDOW_SET == NULL)
		return Py_None;
	return WINDOW_SET;
}

/** 
 * convert the absolute pos (row, col) to the buffer pos,
 * if row or col equal -1, the use the window's current pos.
 */
pos_T
PvWindow_BufferPos(PyObject *self, int row, int col)
{
	pos_T		ret;
	int			i, len, cell;
	PyObject	*line;
	Py_UNICODE	*text, c;
	PyObject	*buf = WIN_BUF(self);

	/* default value */
	if (row == -1)
		row = WIN_ROW(self);
	if (col == -1)
		col = WIN_WCOL(self);

	ret.x = ret.y = 0;
	if (PvBuffer_IsEmpty(buf)) 
		goto end;

	/* handle the row out of range */
	line = PvBuffer_GetLine(buf, row);
	if (line == NULL) {
		PyErr_Clear();
		row = BUF_LEN(buf) - 1;
		line = PvBuffer_GetLine(buf, row);
	}

	len = PyUnicode_GetSize(line);
	text = PyUnicode_AS_UNICODE(line);

	for (i = 0; i < len && ret.x < col; i++) {
		c = text[i];
		if (c == 0)		/* end of line */
			break;
		cell = wcwidth(c);
		if (cell == 1)
			ret.x++;
		else if (cell == 2)
			ret.x += 2;
		else if (cell == -1) {
			if (c == '\t')
				ret.x += COMPUTE_TAB(ret.x, WIN_TABSTOP(self));
			else if (c == '\n')
				break;
		}
	}

	if (ret.x <= col)
		ret.x = i;
	else
		ret.x = i - 1;
	ret.y = row;
end:
	return ret;
}

PyDoc_STRVAR(window_buffer_pos_doc,
"window.buffer_pos(row, col)\n"
"conver the absolute window pos (row, col) to buffer pos\n");

static PyObject *
window_buffer_pos(PyObject *self, PyObject *args)
{
	int		row, col;
	pos_T	ret;

	row = col = -1;
	if (!PyArg_ParseTuple(args, "|ii", &row, &col))
		return NULL;

	ret = PvWindow_BufferPos(self, row, col);
	return Py_BuildValue("(i, i)", ret.y, ret.x);
}

/** 
 * convert the buffer pos (row, col) to the absolute pos,
 * if row or col equal -1, the use the window's current pos.
 */
pos_T
PvWindow_WindowPos(PyObject *self, int row, int col)
{
	pos_T		ret;
	int			i, len, cell;
	PyObject	*line;
	Py_UNICODE	*text, c;
	PyObject	*buf = WIN_BUF(self);

	/* default value */
	if (row == -1)
		row = WIN_ROW(self);
	if (col == -1)
		col = WIN_COL(self);

	ret.x = ret.y = 0;
	if (PvBuffer_IsEmpty(buf)) 
		goto end;
	ret.y = row;

	/* handle the row out of range */
	line = PvBuffer_GetLine(buf, row);
	if (line == NULL) {
		PyErr_Clear();
		ret.y = BUF_LEN(buf) - 1;
		line = PvBuffer_GetLine(buf, ret.y);
	}

	len = PyUnicode_GetSize(line);
	len = MIN(len, col);
	text = PyUnicode_AS_UNICODE(line);

	for (i = 0; i < len; i++) {
		c = text[i];
		if (c == 0)		/* end of line */
			break;
		cell = wcwidth(c);
		if (cell == 1)
			ret.x++;
		else if (cell == 2)
			ret.x += 2;
		else if (cell == -1) {
			if (c == '\t')
				ret.x += COMPUTE_TAB(ret.x, WIN_TABSTOP(self));
			else if (c == '\n')
				break;
		}
	}
end:
	return ret;
}


PyDoc_STRVAR(window_window_pos_doc,
"window.window_pos(row, col)\n"
"conver the buffer pos (row, col) to absolute window pos\n");

static PyObject *
window_window_pos(PyObject *self, PyObject *args)
{
	int		row, col;
	pos_T	ret;

	row = col = -1;
	if (!PyArg_ParseTuple(args, "|ii", &row, &col))
		return NULL;

	ret = PvWindow_WindowPos(self, row, col);
	return Py_BuildValue("(i, i)", ret.y, ret.x);
}

static void
PvWindow_Adjust(PyObject *self)
{
	if (PvWindow_CursorInWindow(self))
		return;
	if (WIN_ROW(self) < WIN_TOPLINE(self))
		WIN_TOPLINE(self) = WIN_ROW(self);
	else if (WIN_ROW(self) >= WIN_TOPLINE(self) + WIN_HEIGHT(self))
		WIN_TOPLINE(self) = WIN_ROW(self) - WIN_HEIGHT(self) + 1;
	if (WIN_WCOL(self) < WIN_LEFTCOL(self))
		WIN_LEFTCOL(self) = WIN_WCOL(self);
	else if (WIN_WCOL(self) >= WIN_LEFTCOL(self) + WIN_WIDTH(self))
		WIN_LEFTCOL(self) = WIN_WCOL(self) - WIN_WIDTH(self) + 1;
	PvWindow_Update(self, 0, 0, WIN_HEIGHT(self) - 1, WIN_WIDTH(self) - 1);
}

/* move to the absolute pos (row, col) */
PyObject *
PvWindow_MoveTo(PyObject *self, int row, int col)
{
	PyObject *line;
	int len;

	if (col < 0)
		col = 0;
	if (row < 0)
		row = 0;
	len = BUF_LEN(WIN_BUF(self));
	if (row >= len)
		row = len - 1;
	line = PvBuffer_GetLine(WIN_BUF(self), row);
	WIN_WANTCOL(self) = WIN_WCOL(self) = col;
	WIN_ROW(self) = row;

	WIN_COL(self) = PvWindow_BufferPos(self, -1, -1).x;
	WIN_WCOL(self) = PvWindow_WindowPos(self, -1, -1).x;
	//printf("%d,%d,%d,%d\n", WIN_ROW(self), WIN_COL(self), WIN_WCOL(self), WIN_WANTCOL(self));
	PvWindow_Adjust(self);
	Py_RETURN_NONE;
}

PyDoc_STRVAR(window_moveto_doc,
"moveto(self, n)\n"
"move to the absolute pos (row, col)\n");

static PyObject *
window_moveto(PyObject *self, PyObject *args)
{
	int row, col;
	if (!PyArg_ParseTuple(args, "ii", &row, &col))
		return NULL;

	return PvWindow_MoveTo(self, row, col);
}


PyObject *
PvWindow_MoveRight(PyObject *self, int n)
{
	PyObject	*line;

	WIN_COL(self) += n;
	line = PvBuffer_GetLine(WIN_BUF(self), WIN_ROW(self));
	if (WIN_COL(self) >= PyUnicode_GetSize(line))
		WIN_COL(self) = PyUnicode_GetSize(line) - 1;
	WIN_WANTCOL(self) = WIN_WCOL(self) = PvWindow_WindowPos(self, -1, -1).x;

	PvWindow_Adjust(self);
	Py_RETURN_NONE;
}

PyObject *
PvWindow_MoveLeft(PyObject *self, int n)
{
	WIN_COL(self) -= n;
	if (WIN_COL(self) < 0)
		WIN_COL(self) = 0;
	WIN_WANTCOL(self) = WIN_WCOL(self) = PvWindow_WindowPos(self, -1, -1).x;

	PvWindow_Adjust(self);
	Py_RETURN_NONE;
}

static PyObject *
PvWindow_MoveV(PyObject *self, int n)
{
	PyObject *line;
	int len;

	WIN_ROW(self) += n;
	len = BUF_LEN(WIN_BUF(self));
	if (WIN_ROW(self) < 0) 
		WIN_ROW(self) = 0;
	else if (WIN_ROW(self) >= len)
		WIN_ROW(self) = len - 1;
	line = PvBuffer_GetLine(WIN_BUF(self), WIN_ROW(self));
	WIN_WCOL(self) = WIN_WANTCOL(self);
	WIN_COL(self) = PvWindow_BufferPos(self, -1, -1).x;
	WIN_WCOL(self) = PvWindow_WindowPos(self, -1, -1).x;
	PvWindow_Adjust(self);
	Py_RETURN_NONE;

}

PyObject *
PvWindow_MoveUp(PyObject *self, int n)
{
	return PvWindow_MoveV(self, -n);
}

PyObject *
PvWindow_MoveDown(PyObject *self, int n)
{
	myprint(BUF_LINES(WIN_BUF(self)));
	return PvWindow_MoveV(self, n);
}

PyDoc_STRVAR(window_mv_left_doc,
"mv_left(self, n)\n"
"move left n step\n");

static PyObject *
window_mv_left(PyObject *self, PyObject *args)
{
	int n = 1;
	if (!PyArg_ParseTuple(args, "|i", &n))
		return NULL;

	return PvWindow_MoveLeft(self, n);
}

PyDoc_STRVAR(window_mv_right_doc,
"mv_right(self, n)\n"
"move right n step\n");

static PyObject *
window_mv_right(PyObject *self, PyObject *args)
{
	int n = 1;
	if (!PyArg_ParseTuple(args, "|i", &n))
		return NULL;

	return PvWindow_MoveRight(self, n);
}

PyDoc_STRVAR(window_mv_up_doc,
"mv_up(self, n)\n"
"move up n step\n");

static PyObject *
window_mv_up(PyObject *self, PyObject *args)
{
	int n = 1;
	if (!PyArg_ParseTuple(args, "|i", &n))
		return NULL;

	return PvWindow_MoveUp(self, n);
}

PyDoc_STRVAR(window_mv_down_doc,
"mv_down(self, n)\n"
"move down n step\n");

static PyObject *
window_mv_down(PyObject *self, PyObject *args)
{
	int n = 1;
	if (!PyArg_ParseTuple(args, "|i", &n))
		return NULL;

	return PvWindow_MoveDown(self, n);
}

/**
 * convert char '\t' to correspond space,
 * and return the number of space(include \t).
 * suppose the col is litter than end, then we can omit the
 * error check. pos end is included in.
 * Argument c is the first char show in screen replace the '\t',
 * remain is space.
 * start: -1, not really insert the char only compute the space
 */
static int
__insert_tab(PyObject *self, Py_UNICODE c, int row, int col, 
		int end, int start)
{
	int fill;
	int remain = COMPUTE_TAB(col, WIN_TABSTOP(self));
	Py_UNICODE *p;

	fill = MIN(remain-1, end-col);
	if (start == -1)
		return fill +1;

	/* you must convert the absolute pos to relative pos to 
	 * compute the address */
	p = LINE_OFFSET(self, ROW_BUF2WIN(self, row)) + COL_BUF2WIN(self, col);
	*p++ = c;
	Py_UNICODE_FILL(p, ' ', fill);

	return fill + 1;
}

/**
 * convert char '\n' to correspond space.
 * suppose the col is litter than end, then we can omit the
 * error check. pos end is included in.
 * Argument c is the first char show in screen replace the '\n',
 * remain is space.
 */
static void
__insert_linebreak(PyObject *self, Py_UNICODE c, 
		int row, int col, int end)
{
	Py_UNICODE *p = LINE_OFFSET(self, ROW_BUF2WIN(self, row));
	*(p+COL_BUF2WIN(self, col)) = c;
	col++;
	while (col <= end) {
		*(p+COL_BUF2WIN(self, col)) = ' ';
		col++;
	}
}

/*
 * convert a buffer line to a window display characters
 * eg. chinese char, \t, \n.
 * because this function use inner this file, it have not error check.
 * it suppose the error condition not toggle.
 * the args row, col1, col2 is for absolute pos,
 * not raw buffer pos or window pos.
 */
static PyObject *
__puts(PyObject *self, int row, Py_UNICODE *line, int len, 
		int col1, int col2)
{
	int i, col, w;
	Py_UNICODE c;
	Py_UNICODE *p;
	int start = -1;		/* tell whether the col in valid range(col1, col2) */

	p = LINE_OFFSET(self, ROW_BUF2WIN(self, row));

	for(i = 0, col = 0; i < len && col <= col2; i++) {
		c = line[i];
		if (c == 0) {
			PyErr_SetString(PyExc_ValueError,
					"Can't handle this zero value now!");
			return NULL;
		}
		if (start == -1 && col >= col1)
			start = col;

		w = wcwidth(c);
		if (w == 1) {
			if (start > -1)
				*(p+COL_BUF2WIN(self, col)) = c;
			col++;
		} else if (w == 2) {
			if (start > -1) {
				*(p+COL_BUF2WIN(self, col)) = c;
				col++;
				if (col <= col2) {
					*(p+COL_BUF2WIN(self, col)) = 0;
					col++;
				}
				else
					break;
			} else
				col += 2;
		} else if (w == -1) {
			if (c == '\t') {
				col += __insert_tab(self, ' ', row, col, col2, start);
			} else if(c == '\n') {
				if (start == -1)
					BLANK_LINE(self, ROW_BUF2WIN(self, row), col2-col1+1);
				else
					__insert_linebreak(self, ' ', row, col, col2);
				break;
			}
		}
	}
	if (start > col1)
		Py_UNICODE_FILL(LINE_OFFSET(self, ROW_BUF2WIN(self, row))
				+COL_BUF2WIN(self, col1),
			   ' ', start-col1);
	Py_RETURN_NONE;
}

/* args of this function is for window pos 
 * not absolute pos or raw buffer pos */
PyObject *
PvWindow_Update(PyObject *self, 
		int row1, int col1, int row2, int col2)
{
	int row, brow, len;
	int buflen;
	PyObject *line;

	buflen = BUF_LEN(WIN_BUF(self));

	row2 = MIN(WIN_HEIGHT(self) - 1, row2);
	col2 = MIN(WIN_WIDTH(self) - 1, col2);
	len = col2 - col1 + 1;
	if (len <= 0)
		Py_RETURN_NONE;

	for (row = row1; row <= row2; row++) {
		brow = ROW_WIN2BUF(self, row);
		if (brow >= buflen) { 
			BLANK_LINE(self, row, len);
			continue;
		}
		line = PvBuffer_GetLine(WIN_BUF(self), brow);
		/* convert buffer line to window line */
		if (!__puts(self, brow, PyUnicode_AS_UNICODE(line),
				PyUnicode_GetSize(line), 
				COL_WIN2BUF(self, col1), COL_WIN2BUF(self, col2)))
			return NULL;
	}
	Py_RETURN_NONE;
}

PyDoc_STRVAR(window_update_doc,
"update(self, row1, col1, row2, col2)\n"
"update window content in (row1, col1, row2, col2)\n");

static PyObject *
window_update(PyObject *self, PyObject *args)
{
	int row1, col1, row2, col2;

	if (!PyArg_ParseTuple(args, "iiii", &row1, &col1, &row2, &col2))
		return NULL;

	PvWindow_Update(self, row1, col1, row2, col2);
	Py_RETURN_NONE;
}

PyObject *
PvWindow_Gets(PyObject *self, int row, int col1, int col2)
{
	if (row >= WIN_HEIGHT(self)) {
		PyErr_SetString(PyExc_ValueError, "The args 'row' is too larger");
		return NULL;
	}
	if (col1 >= WIN_WIDTH(self)) {
		PyErr_SetString(PyExc_ValueError, "The args 'col1' is too larger");
		return NULL;
	}
	col2 = MIN(col2, WIN_WIDTH(self));

	return PyUnicode_FromUnicode(LINE_OFFSET(self, row)+col1, col2-col1+1);
}

PyDoc_STRVAR(window_gets_doc,
"gets(self, row, col1, col2)\n"
"get the line at row, characters beweet offset col1 and col2 (include col2)\n"
"the line is the line store in self.lines\n");

static PyObject *
window_gets(PyObject *self, PyObject *args)
{
	int row, col1, col2;

	if (!PyArg_ParseTuple(args, "iii", &row, &col1, &col2))
		return NULL;

	return PvWindow_Gets(self, row, col1, col2);
}

static PyGetSetDef window_getseters[] = {
	//{"windows", (getter)window_getwindows, (setter)window_setwindows, 
	//	"a set stored all windows reference"},
	{NULL}
};

static PyMemberDef window_members[] = {
	{"buffer", T_OBJECT, offsetof(PvWindow, buffer), 0, 
		"buffer of the window"},
	{"frame", T_OBJECT, offsetof(PvWindow, frame), 0, 
		"frame contain this window"},
	{"topline", T_INT, offsetof(PvWindow, topline), 0, 
		"buffer line number of the line at the top of the window"},
	{"leftcol", T_INT, offsetof(PvWindow, leftcol), 0, 
		"left most window column"},
	{"top", T_INT, offsetof(PvWindow, top), 0, 
		"first row of window in screen"},
	{"height", T_INT, offsetof(PvWindow, height), 0, 
		"number of rows in window, excluding status/command lines"},
	{"left", T_INT, offsetof(PvWindow, left), 0, 
		"leftmost column of window in screen"},
	{"width", T_INT, offsetof(PvWindow, width), 0, 
		"width of window, excluding separation"},
	{"status_height", T_INT, offsetof(PvWindow, status_height), 0, 
		"number of status lines (0 or 1)"},
	{"vsep_width", T_INT, offsetof(PvWindow, vsep_width), 0, 
		"number of separator columns (0 or 1)"},
	{"tabstop", T_INT, offsetof(PvWindow, tabstop), 0, 
		"the step of a \\t char"},
	{"col", T_INT, offsetof(PvWindow, col), 0, 
		"the curren offset in current line in buffer"},
	{"row", T_INT, offsetof(PvWindow, row), 0, 
		"the current line number in buffer"},
	{"wantcol", T_INT, offsetof(PvWindow, wantcol), 0, 
		"the col should to be(absolute pos)"},
	{"wcol", T_INT, offsetof(PvWindow, wcol), 0, 
		"the absolute pos of the col"},
	{NULL}
};

static PyMethodDef window_methods[] = {
	{"update", (PyCFunction)window_update, METH_VARARGS,
		window_update_doc},
	{"gets", (PyCFunction)window_gets, METH_VARARGS,
		window_gets_doc},
	{"bufferpos", (PyCFunction)window_buffer_pos, METH_VARARGS,
		window_buffer_pos_doc},
	{"windowpos", (PyCFunction)window_window_pos, METH_VARARGS,
		window_window_pos_doc},
	{"moveto", (PyCFunction)window_moveto, METH_VARARGS,
		window_moveto_doc},
	{"mv_left", (PyCFunction)window_mv_left, METH_VARARGS,
		window_mv_left_doc},
	{"mv_right", (PyCFunction)window_mv_right, METH_VARARGS,
		window_mv_right_doc},
	{"mv_up", (PyCFunction)window_mv_up, METH_VARARGS,
		window_mv_up_doc},
	{"mv_down", (PyCFunction)window_mv_down, METH_VARARGS,
		window_mv_down_doc},
	{"remove", (PyCFunction)window_remove, METH_VARARGS | METH_STATIC,
		window_remove_doc},
	{"getwindows", (PyCFunction)window_getwindows, METH_NOARGS | METH_STATIC,
		window_getwindows_doc},
	{NULL, NULL}
};


PyTypeObject PvWindow_Type = {
	PyObject_HEAD_INIT(0)
        "pyvim.window",		/* tp_name */
        sizeof(PvWindow),		/* tp_basicsize */
        0,				/* tp_itemsize */
        window_dealloc,		/* tp_dealloc */
        0,				/* tp_print */
        0,				/* tp_getattr */
        0,				/* tp_setattr */
        0,				/* tp_reserved */
        0,				/* tp_repr */
        0,				/* tp_as_number */
        0,				/* tp_as_sequence */
        0,				/* tp_as_mapping */
        0,				/* tp_hash */
        0,				/* tp_call */
        0,				/* tp_str */
        PyObject_GenericGetAttr,	/* tp_getattro */
        0,				/* tp_setattro */
        0,				/* tp_as_buffer */
        Py_TPFLAGS_DEFAULT,		/* tp_flags */
        window_doc,		/* tp_doc */
        0,				/* tp_traverse */
        0,				/* tp_clear */
        0,				/* tp_richcompare */
        0,				/* tp_weaklistoffset */
        0,				/* tp_iter */
        0,				/* tp_iternext */
        window_methods,		/* tp_methods */
        window_members,				/* tp_members */
        window_getseters,				/* tp_getset */
        0,				/* tp_base */
        0,				/* tp_dict */
        0,				/* tp_descr_get */
        0,				/* tp_descr_set */
        0,				/* tp_dictoffset */
        (initproc)window_init,				/* tp_init */
        0,				/* tp_alloc */
        window_new,				/* tp_new */
        0,				/* tp_free */
        0,				/* tp_is_gc */
};

/*
Local variables:
c-basic-offset: 4
indent-tabs-mode: nil
End:
*/
